import axios, {
  AxiosResponse,
  AxiosRequestConfig,
  AxiosInstance,
  Canceler
} from 'axios'
import { AxiosRequestConfigEnhance } from '~/types/shims'
import { ResultEnum } from '~/types/http'
import { useUser } from '@/store/modules/user'
import { useHttp } from '@/store/modules/http'
import { router } from '@/router'
import config from '@/config'
import { uuid } from '@/utils/uuid'

const CancelToken = axios.CancelToken
export const baseURL = config.baseURL
export const timeout = config.timeout

let num = 0
const requests: any[] = []

const flag = {
  hasNoPermissionMsg: false,
  refreshToking: false,
  serverErr: false
}

const axiosInstance: AxiosInstance = axios.create({
  baseURL,
  timeout
})

//刷新token
// const tryRefreshToken = async (config) => {
//   num > 0 && num--
//   if (!flag.refreshToking) {
//     flag.refreshToking = true
//     try {
//       const user = useUser()
//       const { refreshToken, loginOut } = user
//       const res = await refreshToken()
//       if (res) {
//         // 已经刷新了token，将所有队列中的请求进行重试
//         requests.forEach((cb) => cb())
//         requests = []
//         return axiosInstance(requestConf(config))
//       } else {
//         loginOut()
//         await noPermission()
//       }
//     } catch (error) {
//       console.error('refreshToken error =>', error)
//       await router.push({ path: '/login', replace: true })
//     } finally {
//       flag.refreshToking = false
//     }
//   } else {
//     return new Promise((resolve) => {
//       // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
//       requests.push(() => {
//         resolve(axiosInstance(requestConf(config)))
//       })
//     })
//   }
// }
//请求拦截配置
const requestConf = (config: AxiosRequestConfigEnhance) => {
  if (num <= 0) {
    num = 0
    window['$loading'].start()
  }
  num++
  const user = useUser()
  const http = useHttp()
  const {
    oauth: { token }
  } = user
  const noToken = config?.noToken ?? false
  config.headers = {
    authorization: !noToken && token ? `Bearer ${token}` : '',
    'Content-Type': 'application/json;charset=UTF-8',
    code: Date.now()
  }
  // 请求Id
  const createRequestID = (defaultId) => {
    const id = defaultId || uuid()
    return id
  }
  config.cancelToken = new CancelToken(function executor(c: Canceler) {
    http.addCancelToken({
      name: createRequestID(config.cancelName) as string,
      cancel: c
    })
  })

  return config
}
//请求拦截器
axiosInstance.interceptors.request.use(
  requestConf,
  (error: AxiosRequestConfig) => {
    return Promise.reject(error)
  }
)
// 响应拦截器
axiosInstance.interceptors.response.use(
  async (res: AxiosResponse) => {
    const http = useHttp()
    num > 0 && num--

    const {
      config: { cancelName }
    } = res as { config: { cancelName?: string } }
    cancelName && http.delCancelToken(cancelName)
    // console.log('res.data', res.data, res)
    const { status, data, code, message } = res.data as {
      status: number
      data: any
      code: string
      message: string
    }
    //请求错误判断 200
    if (status === ResultEnum.SUCCESS) {
      if (code != '0000') {
        window['$message'].error(`${message}`)
        http.addErrRequest(res)
      }
      // 401
    } else if (status === ResultEnum.NO_PERMISSION) {
      // const user = useUser()
      // const {
      //   oauth: { refreshToken }
      // } = user
      // if (refreshToken) {
      //   return await tryRefreshToken(res.config)
      // } else {
      await noPermission()
      // }
    } else {
      http.addErrRequest(res)
      window['$message'].error(
        `请求失败，状态码：${status ?? res.response?.status}`
      )
      window['$loading'].error()
      num = 0
    }
    if (num >= 0) window['$loading'].finish()
    return Promise.resolve(
      {
        data,
        code,
        message
      } ?? { code: '4004' }
    )
  },
  (err: AxiosResponse) => {
    num > 0 && num--
    if (num >= 0) window['$loading'].finish()
    const {
      config: { cancelName }
    } = err as { config: { cancelName?: string } }
    const http = useHttp()
    http.addErrRequest(err)
    cancelName && http.delCancelToken(cancelName)
    window['$loading'].error()

    !flag.serverErr &&
      window['$message'].error('服务器异常!', {
        onAfterLeave() {
          flag.serverErr = false
        }
      })
    flag.serverErr = true
    console.log(err)
    return Promise.resolve({ code: '4004' })
  }
)

async function noPermission() {
  num = 0
  if (!flag.hasNoPermissionMsg) {
    flag.hasNoPermissionMsg = true
    window['$loading'].error()
    window['$message'].error('登录失败请重新登录', {
      onAfterLeave() {
        flag.hasNoPermissionMsg = false
      }
    })
    await router.push({ path: '/login', replace: true })
  }
}

export default axiosInstance
